package com.hjm.security.service;


import cn.hutool.core.util.StrUtil;
import com.hjm.common.core.constants.CacheConstants;
import com.hjm.common.core.constants.HttpConstants;
import com.hjm.common.core.constants.SecurityConstants;
import com.hjm.common.core.domain.suser.LoginUser;
import com.hjm.common.core.utils.JwtUtils;
import com.hjm.redis.service.RedisService;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * token验证处理
 */
@Component
@Slf4j
public class TokenService {
    @Autowired
    private RedisService redisService;

    @Value("${jwt.secret}")
    String secret;

     /**
     * 创建令牌
     */
    public String createToken(Long userId,Integer Identity,String nickName,String headImage) {
        // 生成token 令牌，并发给客户端
        // 存储敏感信息在redis 中
        Map<String,Object> map = new HashMap<>();
        String userKey=UUID.randomUUID().toString();

        map.put(SecurityConstants.USER_ID,userId);
        // 这里 使用 唯一标识 在 redis 标记 信息
        map.put(SecurityConstants.USER_KEY,userKey);

        String token = JwtUtils.createToken(map,secret);


        String key= CacheConstants.LOGIN_TOKEN_KEY+userKey;

        LoginUser loginUser = new LoginUser();

        // 传入一些基本信息
        loginUser.setIdentity(Identity);
        loginUser.setHeadImage(headImage);
        loginUser.setNickName(nickName);

        // 将 存储的敏感信息 存储到 redis  并用唯一标识 进行标记
        redisService.setCacheObject(key,loginUser,CacheConstants.EXPIRATION, TimeUnit.MINUTES);

        return token;
    }


    /*
    * 延长 token 过期时间*/
    public void extendToken(String token) {
//        Claims claims;
//
//        try{
//            claims = JwtUtils.parseToken(token, secret);
//            if(claims == null) {
//                return;
//            }
//        }catch (Exception e){
//            return;
//        }
//        String userKey=JwtUtils.getUserKey(claims);

        String userKey=getUserKey(token);

        String key=getTokenKey(userKey);   // redis 中的 key


        Long expire = redisService.getExpire(key,TimeUnit.MINUTES);
        // 更新过期时间
        if(expire!=null && expire <= CacheConstants.REFRESH_TIME) {
            redisService.setCacheObject(key,token,CacheConstants.EXPIRATION, TimeUnit.MINUTES);
        }

    }


    // 根据 token  和 secret 获取 登录用户  信息
    public LoginUser getLoginUser(String token){

        String userKey = getUserKey(getToken(token));
        String tokenKey=getTokenKey(userKey);
        if(tokenKey == null )
            return null;
        return redisService.getCacheObject(tokenKey,LoginUser.class);
    }

    public boolean deleteLoginUser(String token){

        String userKey = getUserKey(getToken(token));
        if(userKey == null )
            return false;
        return redisService.deleteObject(getTokenKey(userKey));
    }



    // 获取 userkey
    public Long getUserId(String token) {
        Claims claims = getClaims(token);
        if (claims == null) return null;

        return Long.parseLong(JwtUtils.getUserId(claims));
    }


    // 获取 userkey
    public String getUserKey(String token) {
        Claims claims = getClaims(token);
        if (claims == null) return null;
        return JwtUtils.getUserKey(claims);
    }


    private Claims getClaims(String token) {
        Claims claims;

        try{
            claims = JwtUtils.parseToken(token, secret);
            if(claims == null) {
                log.error("token:{} 解析错误 ", token);
                return null;
            }
        }catch (Exception e){
            log.error("token:{} 解析错误： ", token,e);
            return null;
        }
        return claims;
    }

    public void refreshLoginUser(String nickName, String headImage, String userKey) {
        String tokenKey = getTokenKey(userKey);
        // redis 中 登陆时存储的 loginUser 信息进行 修改
        LoginUser loginUser = redisService.getCacheObject(tokenKey,LoginUser.class);
        loginUser.setNickName(nickName);
        loginUser.setHeadImage(headImage);
        redisService.setCacheObject(tokenKey,loginUser,CacheConstants.EXPIRATION, TimeUnit.MINUTES);
    }


    public String getTokenKey(String userKey){
        return CacheConstants.LOGIN_TOKEN_KEY+userKey;
    }

    public String getToken(String token){
        if (StrUtil.isNotEmpty(token) &&
                token.startsWith(HttpConstants.PREFIX)) {
            token = token.replaceFirst(HttpConstants.PREFIX, StrUtil.EMPTY);
        }
        return token;
    }



}